#!/usr/bin/env python
# -*- coding:utf-8 -*-

import math


"""
默认参数一定要用不可变对象.
*args 是可变参数, args接收的是一个tuple.
**kw是关键字参数,kw接收的是一个dict.

命名的关键字参数是为了限制调用者可以传入的参数名,可提供默认值.
定义命名的关键字参数不要忘了写分隔符*.
"""


# 函数
"""
空函数: pass语句. pass作为占位符.
数据类型检查用内置函数isinstance()。
函数可以使用默认参数,可变参数和关键字参数.

设置默认参数时,要注意:
    1.必选参数在前,默认参数在后.
    2.如何设置默认参数.
    当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面.
    变化小的参数就可以作为默认参数.

定义默认参数要牢记一点: 默认参数必须指向不变对象.

不变对象一旦创建,对象内部的数据就不能修改.


定义可变参数:
    在参数前面加了一个*号，
    在函数内部,参数numbers接收到的是一个tuple.

关键字参数:
    可变参数允许传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple.

    关键字参数允许传入0个或任意个含参数名的参数,关键字参数在函数内部自动组装为一个dict.
"""
"""
def my_abs(x):
    if not isinstance(x,(int,float)):
        raise TypeError('bad operand type')
    if x >= 0:
        return x
    else:
        return -x

print(my_abs(10))
print(my_abs('abd'))
"""




# 返回多个值
"""
def move(x,y,step,angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx,ny

x,y = move(100,100,60, math.pi / 6)
print(x,y)

r = move(100,100,60,math.pi / 6)
print(r)
"""




# 关键字参数
"""
def person(name,age,**kw):
    print('name:',name,'age:',age,'other:',kw)
    # 调用该函数时,可只传入必选参数.

print(person('Michael',30))

# 传入任意个数的关键字参数
print(person('Bob',35,city='Beijing'))
print(person('Adam',45,gender='M',job='Engineer'))

# 先组装一个dict,把该dict转换为关键字参数
extra = {'city':'Beijing','job':'Engineer'}
print(person('Jack',24,city=extra['city'],job=extra['job']))

# 用简化的写法:
extra = {'city':'Beijing','job':'Engineer'}
print(person('Jack',24,**extra))
# **extra把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,
# kw将获得一个dict.
"""






# 命名关键字参数
"""
函数的调用者可传入任意不受限制的关键字参数.
限制关键字参数的名字,可用命名关键字参数.

命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数.
"""
"""
def person(name,age,*,city,job):
    print(name,age,city,job)

print(person('Jack',24,city='Beijing',job='Engineer'))
"""



# 命名关键字参数可以有缺省值,从而简化调用.
def person(name,age,*,city='Beijing',job):
    print(name,age,city,job)

# 命名关键字参数city具有默认值,调用时,可不传入city参数.
print(person('Jack',24,job='Enggineer'))




# 参数组合.
"""
参数定义顺序是:
  必选参数,默认参数,可变参数/命名关键字参数和关键字参数.
"""
# 定义一个函数,包含上述若干种参数
def f1(a,b,c=0,*args,**kw):
    print('a =',a,'b =',b,'c =',c,'args =',args,'kw =',kw)

def f2(a,b,c=0,*,d,**kw):
    print('a =',a,'b =',b,'c =',c, 'd =',d, 'kw =',kw)


print(f1(1,2))
print(f1(1,2,c=3))
print(f1(1,2,3,'a','b'))
print(f1(1,2,3,'a','b',x=99))
print(f2(1,2,d=99,ext=None))

# 通过一个tuple和dict,可调用上述函数
args = (1,2,3,4)
kw = {'d':99,'x':'#'}
print(f1(*args,**kw))
args = (1,2,3)
kw = {'d':88,'x':'#'}
print(f2(*args,**kw))


